<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>v-for指令</title>
    <style>
      li {
        list-style: none;
      }
    </style>
  </head>
  <body>
    <div id="root">
      <!-- 列表渲染
            v-for指令：
              1.用于展示列表数据
              2.语法：v-for='(item,index) in xxx' :key='yyy'
              3.可遍历数组、对象、字符串、指定次数
            key的作用：
              1.key是虚拟DOM对象的标识，当状态中的数据发生变化时，Vue会根据新数据生成新的虚拟DOM，随后Vue进行新旧虚拟DOM的比较
              2.新旧虚拟DOM的比较：
                  1)旧虚拟DOM中找到了和新虚拟DOM相同的key：
                      1.若虚拟DOM内容没变，则直接使用之前的真实DOM
                      2.若虚拟DOM内容发生改变，则生成新的真实DOM，然后替换页面中之前的真实DOM
                  2)旧虚拟DOM中没有找到和新虚拟DOM相同的key：
                      创建新的真实DOM，然后渲染到页面
              3.用index作为key可能引发的问题：
                  1)若对数据进行：逆序添加、逆序删除等破坏顺序操作：
                      会产生没有必要的真实DOM更新，虽然页面效果没问题，但是效率低
                  2)如果结构中还包括输入类DOM：
                      会产生错误的DOM更新，页面效果就可能出问题
              4.开发中 key的选择：
                  1.最好使用每条数据的唯一标识作为key，如id、手机号、身份证号码、学号等唯一值
                  2.如果不存在对数据的逆序添加、逆序删除等破坏顺序操作，仅用于渲染列表用于展示，使用index作为key是没问题的 -->

      <!-- 遍历数组 -->
      <h2>遍历数组:人员列表</h2>
      <ul>
        <li v-for="(person,index) in persons" :key="person.id">
          {{person.name}}-{{person.age}}
        </li>
      </ul>
      <!-- 遍历对象 -->
      <h2>遍历对象:汽车信息</h2>
      <ul>
        <li v-for="(value,key) of car" :key="key">{{key}}-{{value}}</li>
      </ul>
      <!-- 遍历字符串 -->
      <h2>遍历字符串</h2>
      <ul>
        <li v-for="(char,index) of str" :key="index">{{char}}-{{index}}</li>
      </ul>
      <!-- 遍历指定次数 -->
      <h2>遍历指定次数</h2>
      <ul>
        <li v-for="(number,index) of 5" :key="index">{{index}}-{{number}}</li>
      </ul>

      <!-- 列表过滤和排序 -->
      <h2>列表过滤和排序:人员名单</h2>
      <input type="text" placeholder="请输入关键字" v-model="keyword" />
      <button @click="sortType=2">年龄升序</button>
      <button @click="sortType=1">年龄降序</button>
      <button @click="sortType=0">原序</button>
      <ul>
        <li v-for="(person,index) of filPersons" :key="person.id">
          {{person.name}}-{{person.age}}
        </li>
      </ul>

      <!-- 列表修改 -->
      <h2>列表修改</h2>
      <button @click.once="add">添加数据</button>
      <button @click="remove">删除数据</button>
      <h2 v-for="maincity in mainCities" :key="maincity.id">
        {{ maincity.name }}
      </h2>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
    <script>
      var vm = new Vue({
        el: "#root",
        data: {
          // 用于列表渲染
          persons: [
            { id: "001", name: "张三", age: 30 },
            { id: "002", name: "李四", age: 18 },
            { id: "003", name: "王五", age: 20 },
          ],
          car: {
            name: "奥迪双钻",
            price: "50",
            color: "white",
          },
          str: "hello",
          //用于列表过滤
          keyword: "",
          //如果用侦听属性实现列表过滤，要配置filPersons
          // filPersons: [],
          //用于列表排序,0原顺序，1降序，2升序
          sortType: 0,

          //用于列表修改
          mainCities: [
            {
              name: "北京",
              id: 100000,
            },
            {
              name: "上海",
              id: 200000,
            },
            {
              name: "深圳",
              id: 518000,
            },
          ],
        },
        methods: {
          add: function () {
            this.mainCities.push({
              name: "广州",
              id: 510000,
            });
          },
          remove: function () {
            this.mainCities.pop();
          },
        },
        // 计算属性实现列表过滤和排序
        computed: {
          filPersons() {
            const arr = this.persons.filter((person) => {
              return person.name.indexOf(this.keyword) !== -1;
            });
            // 判断是否需要排序
            if (this.sortType) {
              arr.sort((p1, p2) => {
                return this.sortType === 1 ? p2.age - p1.age : p1.age - p2.age;
              });
            }
            return arr;
          },
        },
        // 侦听属性实现列表过滤
        /* watch: {
          keyword: {
            immediate: true,
            handler(val) {
              this.filPersons = this.persons.filter((person) => {
                return person.name.indexOf(this.keyword) !== -1;
              });
            },
          },
        }, */
      });
    </script>
  </body>
</html>
